package thinkinjava.c21_concurrency;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static net.mindview.util.Print.print;

/**
 * @Auther DRevelation
 * @Date 2020-05-13 上午 9:31
 * @Desc
 */
public class CountDownLauchDemo {
    private static final int SIZE = 10;

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        CountDownLatch latch = new CountDownLatch(SIZE);
        for (int i = 0; i < 10; i++) {
            exec.execute(new WaitingTask(latch));
        }
        for (int i = 0; i < SIZE; i++) {
            exec.execute(new TaskPortion(latch));
        }
        print("Launched all tasks");
        exec.shutdown();
    }

    static class TaskPortion implements Runnable {
        private static int count = 0;
        private final int id = count++;
        private static Random rand = new Random(47);
        private final CountDownLatch latch;

        public TaskPortion(CountDownLatch latch) {
            this.latch = latch;
        }
        @Override
        public void run() {
            try {
                doWork();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        }
        public void doWork() throws InterruptedException {
            TimeUnit.MILLISECONDS.sleep(rand.nextInt(2000));
            print(this + " completed");
        }
        @Override
        public String toString() {
            return String.format("%1$-3d", id);
        }
    }

    static class WaitingTask implements Runnable {
        private static int counter = 0;
        private final int id = counter++;
        private final CountDownLatch latch;

        WaitingTask(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                latch.await();
                print("Latch barrier passed for " + this);
            } catch (InterruptedException e) {
                print(this + " interrupted");
                e.printStackTrace();
            }
        }
        @Override
        public String toString() {
            return String.format("WaitingTask %1$-3d ", id);
        }
    }
}
